<?php

class CoverageUtils
{
    public static function parseTextDox($path)
    {
        $tests = array();
        if ($path != '') {
            $cont = explode("\n", file_get_contents($path));
            $group = null;
            foreach ($cont as $line) {
                $symb = $line{0};
                $line = trim($line);
                if ($line == '') {
                } else if ($symb == ' ') {
                    $group[trim(substr($line,3))] = ($line{1} == 'x');
                } else {
                    $tests[$line] = array();
                    $group = &$tests[$line];
                }
            }
        }
        return $tests;
    }

    public static function addTestObject($elem, $objects)
    {
        $attr = $elem->attributes();
        $mattr = $elem->metrics->attributes();
        if ((string)$attr->name != '') {
            $methods = (int)$mattr->methods;
            $coveredmethods = (int)$mattr->coveredmethods;
            if ($coveredmethods > $methods)
                $coveredmethods = $methods;

            $statements = (int)$mattr->statements;
            $coveredstatements = (int)$mattr->coveredstatements;
            if ($coveredstatements > $statements)
                $coveredstatements = $statements;

            $elements = (int)$mattr->elements;
            $coveredelements = (int)$mattr->coveredelements;
            if ($coveredelements > $elements)
                $coveredelements = $elements;
            
            $procelements = $coveredelements / $elements * 100;
            $procmethods = $coveredmethods / $methods * 100;
            $procstatements = $coveredstatements / $statements * 100;
            $total = ($procmethods + $procstatements) / 2;

            /*$this->testObjects[(string)$attr->name] = */
			$name = (string)$attr->name;
			$info = array(
                'methods' => $methods,
                'coveredmethods' => $coveredmethods,
                'statements' => $statements,
                'coveredstatements' => $coveredstatements,
                'elements' => $elements,
                'coveredelements' => $coveredelements,
                'procelements' => $procelements,
                'procmethods' => $procmethods,
                'procstatements' => $procstatements,
                'total' => $total
            );
			$objects[$name] = $info;
        }
    }

    /**
     * Парсить загальний файл
     */
    public static function parseCoverageFile($file)
    {
        $xmlTest = simplexml_load_file($file);
        if (is_null($xmlTest)) {
            return null;
        }
        echo '<pre>';
        $files = array();
        foreach ($xmlTest->project->children() as $child) {
            if ($child->getName() == 'file') {
                //$childs2 = $this->xmlTest->project->file->children();
                $objects = array();
                $metrics = array();

                if (isset($child->class)) {
                    self::addTestObject($child->class, &$objects);
                }

                /*foreach ($child->line->children() as $child3) {
                    $attr = $child3->attributes();
                    if ($child3->getName() == 'line') {
                        $lines[(string)$attr->num] = array(
                            'type' => (string)$attr->type,
                            'count' => (string)$attr->count,
                        );
                    } 
                }*/

                $attr = $child->metrics->attributes();
                $metrics = array(
                    'loc' => (string)$attr->loc,
                    'ncloc' => (string)$attr->ncloc,
                    'classes' => (string)$attr->classes,
                    'methods' => (string)$attr->methods,
                    'coveredmethods' => (string)$attr->coveredmethods,
                    'statements' => (string)$attr->statements,
                    'coveredstatements' => (string)$attr->coveredstatements,
                    'elements' => (string)$attr->elements,
                    'coveredelements' => (string)$attr->coveredelements
                );
                $name = (string)$child->attributes()->name;
                //$this->testFiles[(string)$child->attributes()->name] = 
                $info = array('objects'=>$objects, 'metrics' => $metrics);

                $files[str_replace('\\', '/', $name)] = $info;
            } else if ($child->getName() == 'metrics') {
                $attr = $child->attributes();
                $info = array(
                    'files' => (string)$attr->files,
                    'loc' => (string)$attr->loc,
                    'ncloc' => (string)$attr->ncloc,
                    'classes' => (string)$attr->classes,
                    'methods' => (string)$attr->methods,
                    'coveredmethods' => (string)$attr->coveredmethods,
                    'statements' => (string)$attr->statements,
                    'coveredstatements' => (string)$attr->coveredstatements,
                    'elements' => (string)$attr->elements,
                    'coveredelements' => (string)$attr->coveredelements
                );
        print_r($info);
            }
        }
        print_r($files);
    }

    /**
     * Парсить всі файли покриття
     */
    public static function parseCoverageFiles($path)
    {
        $coverageFiles = array();
        foreach (glob($path . "/*.xml") as $filename) {
            $parsed = self::parseCoverageFileFileInfo($filename);
            if ($parsed != null) {
                $coverageFiles[ $parsed['file'] ] = $parsed;
            }
        }
        //print_r($coverageFiles);
        return $coverageFiles;
    }

    /**
     * Парсить інфо про покриття для файлу
     */
    public static function parseCoverageFileFileInfo($file)
    {
        if (file_exists($file)) {
            $xml = simplexml_load_file($file);
        }
        if (!is_null($xml)) {
            $xfile = '/'.(string)$xml->attributes()->shortenedPath;
            //print $xfile."\n";
            $info = array('file' => $xfile);
            $lines = array();
            foreach ($xml->children() as $child) {
                $num = (string)$child->attributes()->lineNumber;
                $count = (string)$child->attributes()->executed;
                $lines[$num] = array('count' => $count);
                if ($count > 0) {
                    $lines[$num]['tests'] = array();
                    foreach ($child->tests->children() as $test) {
                        $lines[$num]['tests'] []= array(
                            'name' => (string)$test->attributes()->name,
                            'status' => (string)$test->attributes()->status,
                            'class' => (string)$test->attributes()->class,
                            'fullPath' => (string)$test->attributes()->fullPath,
                            'line' => (string)$test->attributes()->line
                            );
                    }
                }
            }
            $info['lines'] = $lines;
            return $info;
        }
        return null;
    }

    public static function checkFileCoverage($source, $path)
    {
        if (self::$coverageFiles == null) {
            self::parseCoverageFiles($path);
        }
        $p = realpath($path);
        $arrSource = explode("\n", $source);
        if (isset(self::$coverageFiles[$p])) {
            $fileInfo = self::$coverageFiles[$p];
            foreach ($arrSource as $k => $line) {
                $lineInfo = array();
                if (isset($fileInfo['lines'][$k + 1])) {
                    $lineInfo = $fileInfo['lines'][$k + 1];
                }
                $style = '';
                $div = '';
                if (isset($lineInfo['count'])) {
                    if ($lineInfo['count'] > 0) {
                        $style = 'line-cover-green';
                        $div = '<div style="float: right; padding-right: 4px;">' . 
                               '<a href="#">' . $lineInfo['count'] . '</a>'
                               . '</div>';
                    } else if ($lineInfo['count'] == -2) {
                        $style = 'line-cover-gray';
                    } else if ($lineInfo['count'] != -3) {
                        $style = 'line-cover-red';
                    }
                }
                $arrSource[$k] = '<li class="' . $style . '"><div class="line-cover ' . $style . '"></div>' . substr($line, 4, -11)
                               . $div
                               . '&nbsp;</div>'
                               . '</li>'
                               . '<div class="spacer"></div>';
            }
        }
        return implode("\n", $arrSource);
    }
}